// 2013年版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package typebits

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/bitvec"
	"cmd/compile/internal/types"
)

// 注意：特定类型t的位图可以在
// 第一次运行，然后以正确的偏移量复制到bv
// 在具有相同类型t的未来调用中。
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
	if t.Align > 0 && off&int64(t.Align-1) != 0 {
		base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
	}
	if !t.HasPointers() {
		// 注意：本例确保要转到的指针为：notinheap类型
		// 垃圾收集和堆栈复制不认为是指针。
		return
	}

	switch t.Kind() {
	case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid alignment, %v", t)
		}
		bv.Set(int32(off / int64(types.PtrSize))) // 指针

	case types.TSTRING:
		// 结构{byte*str；intgo len；}
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid alignment, %v", t)
		}
		bv.Set(int32(off / int64(types.PtrSize))) // 第一个插槽中的指针

	case types.TINTER:
		// 结构{Itab*选项卡；void*数据；}
		// 或者，当isnilinter（t）=真时：
		// 结构{Type*Type；void*data；}
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid alignment, %v", t)
		}
		// 接口的第一个字是指针，但我们没有
		// 就这样对待它。
		// 1.如果是非空接口，指针将指向itab
		// 它总是在persistentalloc空间中。
		// 2.如果是空接口，指针将指向_类型。
		// A.如果它是编译时分配的类型，则指向
		// 只读数据部分。
		// B如果它是反射分配的类型，则指向Go堆。
		// Reflect负责保存对
		// 基础类型，因此它不会是GCd。
		// 如果我们有一个移动GC，我们需要将其更改为2b（如图所示）
		// 以及扫描itab以更新其itab.\u类型字段）。
		bv.Set(int32(off/int64(types.PtrSize) + 1)) // 第二个插槽中的指针

	case types.TSLICE:
		// 结构{byte*数组；uintgo len；uintgo cap；}
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid TARRAY alignment, %v", t)
		}
		bv.Set(int32(off / int64(types.PtrSize))) // 第一个插槽中的指针（位帧）

	case types.TARRAY:
		elt := t.Elem()
		if elt.Width == 0 {
			// 对#20739短路。
			break
		}
		for i := int64(0); i < t.NumElem(); i++ {
			Set(elt, off, bv)
			off += elt.Width
		}

	case types.TSTRUCT:
		for _, f := range t.Fields().Slice() {
			Set(f.Type, off+f.Offset, bv)
		}

	default:
		base.Fatalf("typebits.Set: unexpected type, %v", t)
	}
}
